package bma.common.langutil.ai;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import bma.common.langutil.ai.common.AIEvent;
import bma.common.langutil.ai.common.AIFunction;
import bma.common.langutil.ai.impl.AIServiceTC1;
import bma.common.langutil.ai.impl.AIStackTC1;
import bma.common.langutil.ai.stack.AIStack;
import bma.common.langutil.ai.vm.AIVM;
import bma.common.langutil.core.ObjectUtil;

public class EventUsercaseTC {

	final org.slf4j.Logger log = org.slf4j.LoggerFactory
			.getLogger(EventUsercaseTC.class);

	AIVM main;

	@Before
	public void setupMain() throws Exception {
		main = new AIVM();
		main.initMain();
	}

	@After
	public void closeMain() {
		main.close();
	}

	/**
	 * AIEvent的用例
	 */
	@Test
	public void event() throws Exception {
		final AIServiceTC1 s = new AIServiceTC1();
		AIStack<Boolean> stack = new AIStackTC1<Boolean>();

		final AIEvent<Boolean> event = AIEvent.createManulResetEvent();

		log.info("wait for event");
		event.waitEvent(new AIFunction<Boolean>() {
			@Override
			public boolean apply(AIStack<Boolean> stack) {
				return s.say(stack, "hello world");
			}
		}, stack);

		main.execute(null, new Runnable() {

			@Override
			public void run() {
				log.info("other thread set event");
				event.setEvent();
			}
		});

		ObjectUtil.waitFor(this, 1000);
	}

	@Test
	public void event_cancel() throws Exception {
		final AIServiceTC1 s = new AIServiceTC1();
		AIStack<Boolean> stack = new AIStackTC1<Boolean>();

		final AIEvent<Boolean> event = AIEvent.createManulResetEvent();

		log.info("wait for event");
		event.waitEvent(new AIFunction<Boolean>() {
			@Override
			public boolean apply(AIStack<Boolean> stack) {
				return s.say(stack, "hello world");
			}
		}, stack);

		event.cancel(stack);

		main.execute(null, new Runnable() {

			@Override
			public void run() {
				log.info("other thread set event");
				event.setEvent();
			}
		});

		ObjectUtil.waitFor(this, 1000);
	}

	@Test
	public void event_timeout() throws Exception {
		final AIServiceTC1 s = new AIServiceTC1();
		AIStack<Boolean> stack = new AIStackTC1<Boolean>();

		final AIEvent<Boolean> event = AIEvent.createManulResetEvent();

		log.info("wait for event");
		event.waitEvent(new AIFunction<Boolean>() {
			@Override
			public boolean apply(AIStack<Boolean> stack) {
				return s.say(stack, "hello world");
			}
		}, stack, 500);

		if (event.checkEvent()) {
			main.execute(null, new Runnable() {

				@Override
				public void run() {
					log.info("other thread set event");
					event.setEvent();
				}
			});
		}

		ObjectUtil.waitFor(this, 1000);
	}

}
